package com.zxb.base.system;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.zaxxer.hikari.HikariDataSource;
import com.zxb.base.system.vo.DatasourceBatchVo;
import com.zxb.core.common.A;
import com.zxb.core.common.C;
import com.zxb.core.common.R;
import com.zxb.core.dao.system.SysDatasource;
import com.zxb.core.dao.system.SysDatasourceDao;
import com.zxb.core.util.JsonUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * @author Zxb
 */
@RestController
@RequiredArgsConstructor
public class DatasourceController {

	private final SysDatasourceDao datasourceDao;
	private final JdbcTemplate jdbcTemplate;

	@PostMapping("/datasource/add")
	public R<?> add(@RequestBody SysDatasource obj) {
		datasourceDao.save(obj);
		return R.success();
	}

	@PostMapping("/datasource/del")
	public R<?> del(@RequestBody List<Long> ids) {
		datasourceDao.removeBatchByIds(ids);
		return R.success();
	}

	@PostMapping("/datasource/update")
	public R<?> update(@RequestBody SysDatasource obj) {
		SysDatasource old = datasourceDao.getById(obj.getId());
		A.isInDatabase(old, "数据源");
		if (datasourceDao.exists(
				new QueryWrapper<SysDatasource>()
						.lambda()
						.eq(SysDatasource::getCode, obj.getCode())
						.ne(SysDatasource::getId, old.getId())
		)) {
			return R.error("数据源编码已经存在");
		}

		BeanUtil.copyProperties(obj, old, C.IGNORED_PROPERTIES);
		datasourceDao.updateById(old);
		return R.success();
	}

	@PostMapping("/datasource/batch")
	public R<?> batch(@RequestBody DatasourceBatchVo datasourceBatchVo) {
		List<Long> idList = datasourceBatchVo.getIdList();
		SysDatasource obj = datasourceBatchVo.getObj();
		Boolean usernameCk = datasourceBatchVo.getUsernameCk();
		Boolean passwdCk = datasourceBatchVo.getPasswdCk();
		Boolean driverClassNameCk = datasourceBatchVo.getDriverClassNameCk();
		for(Long id:idList) {
			SysDatasource oldObj = datasourceDao.getById(id);
			if(usernameCk){
				oldObj.setUsername(obj.getUsername());
			}
			if(passwdCk){
				oldObj.setPasswd(obj.getPasswd());
			}
			if(driverClassNameCk){
				oldObj.setDriverClassName(obj.getDriverClassName());
			}
			datasourceDao.updateById(oldObj);
		}
		return R.success();
	}

	@GetMapping("/datasource/info")
	public R<?> info(Long id) {
		SysDatasource obj = datasourceDao.getById(id);
		return R.success(obj);
	}

	@GetMapping("/datasource/list")
	public R<?> list() {
		return R.success(datasourceDao.list());
	}


	@GetMapping("/datasource/page")
	public R<?> page(String searchStr, Integer page, Integer pageSize) {
		IPage<SysDatasource> pageParam = new Page<>(page, pageSize);
		LambdaQueryWrapper<SysDatasource> queryWrapper = new LambdaQueryWrapper<>();
		if (StrUtil.isNotBlank(searchStr)) {
			queryWrapper.like(SysDatasource::getCode, "%" + searchStr + "%");
		}
		IPage<SysDatasource> result = datasourceDao.page(pageParam, queryWrapper);
		return R.success(result);
	}

	@GetMapping("/datasource/test")
	public R<?> test(String key){
		Integer count = jdbcTemplate.queryForObject("select count(1) from sys_datasource where code = ?", Integer.class, key);
		if (count == null || count == 0) {
			return R.error("数据源编码不存在");
		}
		Map<String, Object> map = jdbcTemplate.queryForMap("select * from sys_datasource where code = ?", key);
		HikariDataSource dataSource = DataSourceBuilder.create()
				.type(HikariDataSource.class)
				.url((String) map.get("jdbc_url"))
				.username((String) map.get("username"))
				.password((String) map.get("passwd"))
				.driverClassName((String) map.get("driver_class_name"))
				.build();
		try {
			Connection conn = dataSource.getConnection();
			DatabaseMetaData metaData = conn.getMetaData();
			ObjectNode on = JsonUtil.on();
			on.put("dataSourceType",dataSource.getClass().toString());
			on.put("conn",conn.toString());
			on.put("url",metaData.getURL());
			on.put("username",metaData.getUserName());
			on.put("driverName",metaData.getDriverName());
			on.put("driverVersion",metaData.getDriverVersion());
			on.put("productName",metaData.getDatabaseProductName());
			on.put("productVersion",metaData.getDatabaseProductVersion());
			return R.success(on);
		} catch (SQLException e) {
			e.printStackTrace();
			return R.error(e.getMessage());
		}
	}
}
